/*=========================================================================

Program:   Virtual Surgery
Language:  C++
Date:      2009-9-1
Version:   0.1
Mail:		   nelfylee@gmail.com

Copyright (c) 2009 Nelfy Lee. All rights reserved.

=========================================================================*/
#include "View2d.h"
#include "Source.h"
#include <stdio.h>
#include <stdlib.h>

#include "vtkImageData.h"
#include "vtkProp3DCollection.h"
#include "vtkSplineWidget.h"
#include "vtkTextProperty.h"
#include "vtkRenderWindow.h"
#include "vtkMatrix4x4.h"
#include "vtkRendererCollection.h"
#include "vtkInteractorStyleImage.h"
#include "vtkLookupTable.h"
#include "vtkImageAppendComponents.h"
#include "vtkImageGridSource.h"
#include "vtkSelectVisiblePoints.h"
#include "vtkLabeledDataMapper.h"
#include "vtkLabelSizeCalculator.h"
#include "vtkPointSetToLabelHierarchy.h"
#include "vtkLabelPlacer.h"
#include "QVTKWidget.h"
#include "vtkLabelHierarchy.h"
#include "vtkEventQtSlotConnect.h"
#include "vtkInteractorStyleRubberBand2D.h"

#include <QTimer>
#include <QWidget>
#include <QtTest/QTest>
#include <QHBoxLayout>
#include <QStyle>
#include <QDebug>
#include <QColorDialog>

static double axialElements[16] = 
{
	1, 0, 0, 0,
	0, 1, 0, 0,
	0, 0, 1, 0,
	0, 0, 0, 1	
};

static double sagittalElements[16] = 
{
	0, 0,-1, 0,
	1, 0, 0, 0,
	0, 1, 0, 0,
	0, 0, 0, 1 
};

static double coronalElements[16] = 
{
	1, 0, 0, 0,			//x ----
	0, 0, 1, 0,			//y
	0, 1, 0, 0,			//z
	0, 0, 0, 1			//w
};


View2D::View2D(const QString &name,int id)
: View(name, id)
{
	int size = style()->pixelMetric(QStyle::PM_ToolBarIconSize);
	QSize iconSize(size, size);

	m_btnCrossLine = new QToolButton;
	m_btnCrossLine->setCheckable(true);
	m_btnCrossLine->setChecked(true);
	m_btnCrossLine->setIcon(QIcon(QPixmap(":/res/bw_add.png")));
	m_btnCrossLine->setIconSize(QSize(16, 16));
	m_btnCrossLine->setAutoRaise(true);

	m_btnTextInfo = new QToolButton;
	m_btnTextInfo->setCheckable(true);
	m_btnTextInfo->setChecked(true);
	m_btnTextInfo->setIcon(QIcon(QPixmap(":/res/bw_info.png")));
	m_btnTextInfo->setAutoRaise(true);

	m_btnResetWL = new QToolButton;
	m_btnResetWL->setIcon(QIcon(QPixmap(":/res/bw_resetWL.png")));
	m_btnResetWL->setAutoRaise(true);
	connect(m_btnResetWL, SIGNAL(clicked()), SLOT(slotResetWindowLevel()));

	m_cbView = new QComboBox;
	m_cbView->insertItems(0, QStringList()
		<< QApplication::translate("Form", "AXIAL", 0, QApplication::UnicodeUTF8)
		<< QApplication::translate("Form", "CORONAL", 0, QApplication::UnicodeUTF8)
		<< QApplication::translate("Form", "SAGITTAL", 0, QApplication::UnicodeUTF8)
		);

	connect(m_cbView, SIGNAL(currentIndexChanged(int)), SLOT(slotViewOrientationChanged(int)));
	m_viewOrientation = voAXIAL;

	m_layoutToolbar->addWidget(m_cbView);
	m_layoutToolbar->addWidget(m_btnResetWL);
	m_layoutToolbar->addWidget(m_btnCrossLine);
	m_layoutToolbar->addWidget(m_btnTextInfo);

	m_pointPicker = vtkPointPicker::New();

	initInternalActors();

	connect(m_btnCrossLine, SIGNAL(toggled(bool)), SLOT(slotEnableCrossLine(bool)));
	connect(m_btnTextInfo, SIGNAL(toggled(bool)), SLOT(slotEnableTextInfo(bool)));

	m_interactorStyle = vtkInteractorStyleImage::New();
	//vtkInteractorStyleRubberBand2D *testStyle = vtkInteractorStyleRubberBand2D::New();
	m_qvtkWidget->GetRenderWindow()->GetInteractor()->SetInteractorStyle(m_interactorStyle);


	vtkEventQtSlotConnect *Connections = vtkEventQtSlotConnect::New();

	Connections->Connect(m_sliderRep,vtkCommand::WidgetValueChangedEvent, this, SLOT(slotChangeSlice(vtkObject*)));
	Connections->Connect(m_sliderWidget,vtkCommand::MouseMoveEvent, this, SLOT(slotSliderMouseMove(vtkObject*)));
	
	Connections->Connect(m_interactorStyle,vtkCommand::LeftButtonPressEvent, this, SLOT(slotLeftButtonPressed(vtkObject*, unsigned long )));
	Connections->Connect(m_interactorStyle,vtkCommand::LeftButtonReleaseEvent, this, SLOT(slotLeftButtonReleased(vtkObject*, unsigned long)));
	Connections->Connect(m_interactorStyle,vtkCommand::MouseMoveEvent, this, SLOT(slotMouseMove(vtkObject*)));
	Connections->Connect(m_interactorStyle,vtkCommand::RightButtonPressEvent, this, SLOT(slotRightButtonPressed(vtkObject*)));
	Connections->Connect(m_interactorStyle,vtkCommand::RightButtonReleaseEvent, this, SLOT(slotRightButtonReleased(vtkObject*)));
	Connections->Connect(m_interactorStyle,vtkCommand::StartWindowLevelEvent, this, SLOT(slotStartWindowLevel(vtkObject*)));
	Connections->Connect(m_interactorStyle,vtkCommand::EnterEvent, this, SLOT(slotMouseEnter(vtkObject*)));
	Connections->Connect(m_interactorStyle,vtkCommand::LeaveEvent, this, SLOT(slotMouseLeave(vtkObject*)));
}


View2D::~View2D()
{

}


void View2D::slotSliderMouseMove(vtkObject*)
{
	//qDebug("Mouse moved in slider");
}



void View2D::initInternalActors()
{
	m_baseActor=NULL;
	m_reslicedImage=NULL;
	m_mapperWindowLevel=NULL;
	m_filterThreshold=NULL;
	m_blendedImage=NULL;
	m_resliceAxes=NULL;


	//////////////////////////////////////////////////////////////////////////
	// Init blending lookup table


	m_blendingLookupTable = vtkLookupTable::New();
	m_blendingLookupTable->SetNumberOfColors(5);
	m_blendingLookupTable->SetTableValue(0,0,0,0,0);
	m_blendingLookupTable->SetTableValue(1,0,1,0,1);
	m_blendingLookupTable->SetTableValue(2,0,1,1,1);
	m_blendingLookupTable->SetTableValue(3,1,0,0,1);
	m_blendingLookupTable->SetTableValue(4,1,0,1,1);

	//////////////////////////////////////////////////////////////////////////
	// Add text info actors

	m_textMapperWindowLevel = vtkTextMapper::New();
	m_textMapperWindowLevel->GetTextProperty()->SetColor(1,1,1);
	m_textMapperWindowLevel->GetTextProperty()->SetFontSize(10);

	m_textMapperIntensityValue  = vtkTextMapper::New();
	m_textMapperIntensityValue->GetTextProperty()->SetColor(1,1,1);
	m_textMapperIntensityValue->GetTextProperty()->SetFontSize(10);


	m_textActorWindowLevel = vtkActor2D::New();
	m_textActorWindowLevel->SetMapper(m_textMapperWindowLevel);
	m_textActorWindowLevel->SetPosition(2, 15);

	m_textActorIntensityValue = vtkActor2D::New();
	m_textActorIntensityValue->SetMapper(m_textMapperIntensityValue);
	m_textActorIntensityValue->SetPosition(2, 2);

	m_renderer->AddActor2D(m_textActorWindowLevel);
	m_renderer->AddActor2D(m_textActorIntensityValue);


	//////////////////////////////////////////////////////////////////////////
	// Add cross lines

	m_sourceCrossLineV = vtkLineSource::New();
	m_sourceCrossLineH = vtkLineSource::New();
	m_mapperCrossLineV = vtkPolyDataMapper2D::New();
	m_mapperCrossLineH = vtkPolyDataMapper2D::New();
	m_actorCrossLineV = vtkActor2D::New();
	m_actorCrossLineH = vtkActor2D::New();

	m_mapperCrossLineV->SetInputConnection(m_sourceCrossLineV->GetOutputPort());
	m_mapperCrossLineH->SetInputConnection(m_sourceCrossLineH->GetOutputPort());


	m_actorCrossLineV->SetMapper(m_mapperCrossLineV);
	m_actorCrossLineH->SetMapper(m_mapperCrossLineH);

	m_actorCrossLineV->GetProperty()->SetColor(65.0, 105.0, 225.0);
	m_actorCrossLineH->GetProperty()->SetColor(65.0, 105.0, 225.0);

	m_renderer->AddActor(m_actorCrossLineV);
	m_renderer->AddActor(m_actorCrossLineH);


	//////////////////////////////////////////////////////////////////////////
	// Add slider widget

	m_sliderRep = vtkSliderRepresentation2D::New();
	m_sliderRep->GetPoint1Coordinate()->SetCoordinateSystemToNormalizedDisplay();
	m_sliderRep->GetPoint1Coordinate()->SetValue(0.1,0.1);
	m_sliderRep->GetPoint2Coordinate()->SetCoordinateSystemToNormalizedDisplay();
	m_sliderRep->GetPoint2Coordinate()->SetValue(0.9,0.1);
	m_sliderRep->SetSliderLength(0.02);
	m_sliderRep->SetSliderWidth(0.04);
 	m_sliderRep->SetEndCapLength(0.01);
 	m_sliderRep->SetEndCapWidth(0.005);
	m_sliderRep->SetTubeWidth(0.005);
	m_sliderRep->SetLabelFormat("%3.0f");
	m_sliderRep->GetSliderProperty()->SetOpacity(0.2);
	m_sliderRep->GetSliderProperty()->SetColor(255.0/255.0, 245.0/255.0, 238.0/255.0);
	m_sliderRep->GetTubeProperty()->SetOpacity(0.2);
	m_sliderRep->GetTubeProperty()->SetColor(255.0/255.0, 245.0/255.0, 238.0/255.0);
	m_sliderRep->GetCapProperty()->SetOpacity(0.2);
	m_sliderRep->GetCapProperty()->SetColor(255.0/255.0, 245.0/255.0, 238.0/255.0);
	m_sliderRep->SetValue(0);

	m_sliderWidget = vtkSliderWidget::New();
	m_sliderWidget->SetInteractor(m_renderer->GetRenderWindow()->GetInteractor());
	m_sliderWidget->SetRepresentation(m_sliderRep);
	m_sliderWidget->SetAnimationModeToAnimate();
	m_sliderValue = -1;
	m_currentSliderStatus = false;
}


void View2D::setBaseThreshold( double lower, double upper)
{
	if ( m_imageList.size() > 0 && m_filterThreshold)
	{
		m_filterThreshold->ThresholdBetween(lower, upper);
		render();
	}
}


void View2D::currEventPos(vtkObject *obj, int pos[3])
{
	m_interactorStyle->GetInteractor()->GetEventPosition(pos);
}

void View2D::slotLeftButtonPressed(vtkObject *obj, unsigned long vtk_even)
{
	View::slotLeftButtonPressed(obj, vtk_even);
	m_interactorStyle->OnLeftButtonDown();

	currEventPos(obj, m_poseLeftPressed);
}

void View2D::slotLeftButtonReleased(vtkObject *obj, unsigned long vtk_even)
{
	View::slotLeftButtonReleased(obj, vtk_even);
	m_interactorStyle->OnLeftButtonUp();

	m_baseWindow = m_tempWindow;
	m_baseLevel = m_tempLevel;

	if ( m_viewMode == vmPickingSeed || m_viewMode == vmPixelGear)
	{
		if ( m_imageList.size() > 0 && m_reslicedImage)
		{
			int curr_pos[3];
			double spacing[3];
			int extent[6];
			double mapvale[3];
			int image_index[3];

			currEventPos(obj, curr_pos);

			m_reslicedImage->GetOutput()->GetSpacing(spacing);
			m_reslicedImage->GetOutput()->GetExtent(extent);

			m_pointPicker->Pick(curr_pos[0], curr_pos[1], 0, m_renderer);
			m_pointPicker->GetMapperPosition(mapvale);

			if ( mapvale[0] <= 0 || mapvale[1] <= 0|| 
				mapvale[0] > (extent[1]+1)*spacing[0]|| 
				mapvale[1] > (extent[3]+1)*spacing[1])
			{
				mapvale[0] = 0;
				mapvale[1] = 0;
				mapvale[2] = 0;
			}


			image_index[0] = (int)(mapvale[0]/spacing[0]);
			image_index[1] = (int)(mapvale[1]/spacing[1]);
			image_index[2] = m_sliderValue;

			if ( image_index[0] != 0 && image_index[1] != 0)
			{
				QString seed = QString("%1,%2,%3").arg(image_index[0]).arg(image_index[1]).arg(image_index[2]);
				m_seedList.prepend(seed);

				emit emitSeedPicked();
			}
		}

		// for picking seed just need once
		if ( m_viewMode == vmPickingSeed)
			setDisplayMode(vmNormal);
	}
}


void View2D::enableSliderWidget(bool flag)
{
	if (flag == m_currentSliderStatus)
		return;

	m_currentSliderStatus = flag;

	if (m_currentSliderStatus)
	{
		m_sliderRep->GetSliderProperty()->SetOpacity(0.8);
		m_sliderRep->GetTubeProperty()->SetOpacity(0.8);
		m_sliderRep->GetCapProperty()->SetOpacity(0.8);
		showCrossLine(false);
	}
	else
	{
		m_sliderRep->GetSliderProperty()->SetOpacity(0.2);
		m_sliderRep->GetTubeProperty()->SetOpacity(0.2);
		m_sliderRep->GetCapProperty()->SetOpacity(0.2);
		showCrossLine(true);
	}
}


void View2D::slotMouseMove(vtkObject *obj)
{
	static int curr_pos[3];
	static double mapvale[3];
	static double spacing[3];
	static int extent[6];
	static float iValue;

	currEventPos(obj, curr_pos);

	if ( m_sliderWidget->GetEnabled())
	{
		if ( curr_pos[0] >= m_sliderPoint1[0] &&
			curr_pos[0] <= m_sliderPoint2[0] &&
			curr_pos[1] >= m_sliderPoint1[1] - 15 &&
			curr_pos[1] <= m_sliderPoint1[1] + 15)
		{
			enableSliderWidget(true);
			render();
			vtkInteractorStyleImage *interactor = vtkInteractorStyleImage::SafeDownCast(obj);
			interactor->OnMouseMove();
			return;
		}
		else
		{
			enableSliderWidget(false);
			render();
		}
	}

	if ( m_imageList.size() > 0)
	{
		if ( m_lbtnPressed == true)
		{
			//double step = 8.0*(m_baseScalar[1] - m_baseScalar[0])/m_size[0];
			double dx = 4.0 * (curr_pos[0] - m_poseLeftPressed[0]) / m_size[0];
			double dy = 4.0 * (curr_pos[1] - m_poseLeftPressed[1]) / m_size[1];

			if (fabs(m_baseWindow) > 0.01)
				dx = dx * m_baseWindow;
			else
				dx = dx * (m_baseWindow < 0 ? -0.01 : 0.01);

			if (fabs(m_baseLevel) > 0.01)
				dy = dy * m_baseLevel;
			else
				dy = dy * (m_baseLevel < 0 ? -0.01 : 0.01);

			if (m_baseWindow < 0.0) 
				dx = -1*dx;
			if (m_baseLevel < 0.0) 
				dy = -1*dy;

			m_tempWindow = dx + m_baseWindow;
			m_tempLevel = m_baseLevel - dy;

			if (fabs(m_tempWindow) < 0.01)
				m_tempWindow = 0.01*(m_tempWindow < 0 ? -1 : 1);

			if (fabs(m_tempLevel) < 0.01)
				m_tempLevel = 0.01*(m_tempLevel < 0 ? -1 : 1);

			char info[128] = {0};
			sprintf(info, "W/L:(%d/%d)", (int)m_tempWindow, (int)m_tempLevel);
			m_textMapperWindowLevel->SetInput(info);

			m_mapperWindowLevel->SetWindow(m_tempWindow);
			m_mapperWindowLevel->SetLevel(m_tempLevel);
		}

		if ( m_reslicedImage && m_btnTextInfo->isChecked())
		{
			static int image_index[3];
			vtkImageData *image = m_imageList.at(0);
			static QString info;

			vtkImageData *image1 = m_reslicedImage->GetOutput();

			image1->GetSpacing(spacing);
			image1->GetExtent(extent);

			m_pointPicker->Pick(curr_pos[0], curr_pos[1], 0, m_renderer);
			m_pointPicker->GetMapperPosition(mapvale);

			if ( mapvale[0] < 0 || mapvale[1] < 0 || 
				mapvale[0] > (extent[1]+1)*spacing[0]|| 
				mapvale[1] > (extent[3]+1)*spacing[1])
			{
				mapvale[0] = 0;
				mapvale[1] = 0;
				mapvale[2] = 0;
			}

			if ( m_viewOrientation == voAXIAL )
			{
				image_index[0] = (int)(mapvale[0]/spacing[0]);
				image_index[1] = (int)(mapvale[1]/spacing[1]);
				image_index[2] = m_sliderValue;
			}
			else if ( m_viewOrientation == voCORONAL)
			{
				image_index[0] = m_sliderValue;
				image_index[1] = (int)m_sliderRep->GetValue();
				image_index[2] = (int)(mapvale[1]/spacing[1]);
			}
			else if ( m_viewOrientation == voSAGITTAL)
			{
				image_index[0] = m_sliderValue;
				image_index[1] = (int)(mapvale[0]/spacing[0]);
				image_index[2] = (int)(mapvale[1]/spacing[1]);
			}

			vtkIdType id = image->ComputePointId(image_index);

			//iValue = ((unsigned char*)image->GetScalarPointer())[id];

			if ( image->GetScalarType()==VTK_SHORT)
			{
				iValue = static_cast<float>(((short*)image->GetScalarPointer())[id]);
			}
			else if ( image->GetScalarType()==VTK_FLOAT)
			{
				iValue = ((float*)image->GetScalarPointer())[id];
			}


			info = QString("[%1:%2, %3]").arg(image_index[0]).arg(image_index[1]).arg(iValue, 0, 'f', 3);

			m_textMapperIntensityValue->SetInput(info.toLocal8Bit().constData());
		}
	}

	if ( m_btnCrossLine->isChecked())
	{
		m_sourceCrossLineV->SetPoint1(0,curr_pos[1],0);
		m_sourceCrossLineV->SetPoint2(m_size[0],curr_pos[1],0);
		m_sourceCrossLineH->SetPoint1(curr_pos[0],0,0);
		m_sourceCrossLineH->SetPoint2(curr_pos[0],m_size[1],0);
		render();
	}

	vtkInteractorStyleImage *interactor = vtkInteractorStyleImage::SafeDownCast(obj);
	interactor->OnMouseMove();
}


void View2D::resizeEvent(QResizeEvent *event)
{
	View::resizeEvent(event);
	vtkCoordinate *coor1 = m_sliderRep->GetPoint1Coordinate();
	vtkCoordinate *coor2 = m_sliderRep->GetPoint2Coordinate();

	m_sliderPoint1 = coor1->GetComputedDisplayValue(m_renderer);
	m_sliderPoint2 = coor2->GetComputedDisplayValue(m_renderer);
}


void View2D::slotRightButtonReleased(vtkObject *obj)
{
	vtkInteractorStyleImage *interactor = vtkInteractorStyleImage::SafeDownCast(obj);

	interactor->OnRightButtonUp();
}


void View2D::slotRightButtonPressed(vtkObject *obj)
{
	vtkInteractorStyleImage *interactor = vtkInteractorStyleImage::SafeDownCast(obj);

	interactor->OnRightButtonDown();
}


void View2D::slotMouseEnter(vtkObject *obj)
{
	if ( m_btnCrossLine->isChecked())
		showCrossLine(true);
}


void View2D::slotMouseLeave(vtkObject *obj)
{
	if ( m_btnCrossLine->isChecked())
		showCrossLine(false);
}


void View2D::changeSlice(int num)
{
	if ( m_viewOrientation == voAXIAL )
		m_resliceAxes->SetElement(2, 3, m_baseSpacing[2]*num);
	else if ( m_viewOrientation == voCORONAL)
		m_resliceAxes->SetElement(1, 3, m_baseSpacing[1]*num);
	else if ( m_viewOrientation == voSAGITTAL)
		m_resliceAxes->SetElement(0, 3, m_baseSpacing[0]*num);
	else
		return;

	render();
}


void View2D::setBaseImage(vtkImageData* image)
{
	clearOutsidePropers();
	
	m_imageList.clear();
	m_imageList.push_back(image);

	//m_viewOrientation = voAXIAL;

	image->GetExtent(m_baseExtent);
	//image->GetWholeExtent(m_baseExtent);
	image->GetSpacing(m_baseSpacing);
	image->GetOrigin(m_baseOrigin);
	image->GetScalarRange(m_baseScalar);
	m_baseWindow = m_baseScalar[1] - m_baseScalar[0];
	m_baseLevel = (m_baseScalar[1] + m_baseScalar[0])/2.0;
	m_tempWindow = m_baseWindow;
	m_tempLevel = m_baseLevel;

	if ( !m_resliceAxes)
		m_resliceAxes = vtkMatrix4x4::New();

	if ( m_viewOrientation == voAXIAL )
	{
		m_resliceAxes->DeepCopy(axialElements);
		m_resliceAxes->SetElement(0, 3, 0);
		m_resliceAxes->SetElement(1, 3, 0);
		m_resliceAxes->SetElement(2, 3, 0);
		m_sliderRep->SetMaximumValue(m_baseExtent[5]);

// 		m_resliceAxes->DeepCopy(axialElements);
// 		m_resliceAxes->SetElement(0, 3, 0);
// 		m_resliceAxes->SetElement(1, 3, 0);
// 		m_resliceAxes->SetElement(2, 3, 0);
// 		m_sliderRep->SetMaximumValue(m_baseExtent[5]);
	}
	else if ( m_viewOrientation == voCORONAL)
	{
		m_resliceAxes->DeepCopy(coronalElements);
		m_resliceAxes->SetElement(0, 3, 0);
		m_resliceAxes->SetElement(1, 3, 0);
		m_resliceAxes->SetElement(2, 3, 0);
		m_sliderRep->SetMaximumValue(m_baseExtent[1]);
	}
	else if ( m_viewOrientation == voSAGITTAL)
	{
		m_resliceAxes->DeepCopy(sagittalElements);
		m_resliceAxes->SetElement(0, 3, 0);
		m_resliceAxes->SetElement(1, 3, 0);
		m_resliceAxes->SetElement(2, 3, 0);
		m_sliderRep->SetMaximumValue(m_baseExtent[3]);
	}
	else
		return;


	m_sliderWidget->EnabledOn();
	m_sliderRep->SetMinimumValue(0);

	vtkCoordinate *coor1 = m_sliderRep->GetPoint1Coordinate();
	vtkCoordinate *coor2 = m_sliderRep->GetPoint2Coordinate();

	m_sliderPoint1 = coor1->GetComputedDisplayValue(m_renderer);
	m_sliderPoint2 = coor2->GetComputedDisplayValue(m_renderer);


	//m_baseSource->setVisibility(true);

	m_sliderRep->SetValue(0);


	if ( !m_filterThreshold)
		m_filterThreshold = vtkImageThreshold::New();
	m_filterThreshold->SetInput(image);
	m_filterThreshold->ThresholdBetween(m_baseScalar[0], m_baseScalar[1]);
	m_filterThreshold->SetOutValue(m_baseScalar[0]);

	if ( !m_mapperWindowLevel)
		m_mapperWindowLevel = vtkImageMapToWindowLevelColors::New();
	m_mapperWindowLevel->SetInputConnection(m_filterThreshold->GetOutputPort());
	m_mapperWindowLevel->SetWindow(m_baseWindow);
	m_mapperWindowLevel->SetLevel(m_baseLevel);
	
	if ( m_blendedImage)
		m_blendedImage->Delete();
	m_blendedImage = vtkImageBlend::New();

	m_blendedImage->SetInput(0, m_mapperWindowLevel->GetOutput());
	m_blendedImage->Update();

	//m_sliderWidget->EnabledOn();

		
	if ( !m_reslicedImage)
		m_reslicedImage = vtkImageReslice::New();

	m_reslicedImage->SetInputConnection(m_blendedImage->GetOutputPort());
	m_reslicedImage->SetOutputDimensionality(2);
	m_reslicedImage->SetResliceAxes(m_resliceAxes);
	//m_reslicedImage->SetResliceTransform(trans);
	m_reslicedImage->SetInterpolationModeToLinear();
	m_reslicedImage->MirrorOff();
	m_reslicedImage->Update();
	
	if ( !m_baseActor)
		m_baseActor = vtkImageActor::New();

	m_baseActor->SetInput(m_reslicedImage->GetOutput());
	m_baseActor->RotateX(180);

	//addProper(m_baseActor);
	m_renderer->AddActor(m_baseActor);

	resetCamera();
	render();
}


void View2D::slotResetWindowLevel()
{
	if ( m_imageList.size() > 0)
	{
		m_baseWindow = m_baseScalar[1] - m_baseScalar[0];
		m_baseLevel = (m_baseScalar[1] + m_baseScalar[0])/2.0;
		m_tempWindow = m_baseWindow;
		m_tempLevel = m_baseLevel;

		if ( m_mapperWindowLevel)
		{
			m_mapperWindowLevel->SetWindow(m_baseWindow);
			m_mapperWindowLevel->SetLevel(m_baseLevel);
			render();
		}
	}
}


void View2D::slotStartWindowLevel(vtkObject *obj)
{

}


// void View2D::slotAddPointLabel(QString point)
// {
// 
// 
// }


void View2D::updatePointLabels()
{
	float p[3];
	p[0] = 100;
	p[1] = 100;
	p[2] = 9;

	vtkPoints *points = vtkPoints::New();
	points->InsertNextPoint(p);

	vtkPolyData *pdata = vtkPolyData::New();
	pdata->SetPoints(points);

	vtkSelectVisiblePoints *visPts = vtkSelectVisiblePoints::New();
	visPts->SetInput(pdata);
	visPts->SetRenderer(m_renderer);



	vtkLabelSizeCalculator *labelSizeCalculator = vtkLabelSizeCalculator::New();
	labelSizeCalculator->SetInput(pdata);
	labelSizeCalculator->GetFontProperty()->SetFontSize( 12 );
	labelSizeCalculator->GetFontProperty()->SetFontFamily( vtkTextProperty::GetFontFamilyFromString( "Arial" ) );
	labelSizeCalculator->SetInputArrayToProcess( 0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "PlaceNames" );
	labelSizeCalculator->SetLabelSizeArrayName( "LabelSize" );


	vtkPointSetToLabelHierarchy *pointSetToLabelHierarchy = vtkPointSetToLabelHierarchy::New();
	pointSetToLabelHierarchy->AddInputConnection(labelSizeCalculator->GetOutputPort());
	pointSetToLabelHierarchy->SetInputArrayToProcess( 0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "Priority" );
	pointSetToLabelHierarchy->SetInputArrayToProcess( 1, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "LabelSize" );
	pointSetToLabelHierarchy->SetInputArrayToProcess( 2, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "PlaceNames" );
	pointSetToLabelHierarchy->SetMaximumDepth( 5 );
	pointSetToLabelHierarchy->SetTargetLabelCount( 32 );

	vtkLabelPlacer *labelPlacer = vtkLabelPlacer::New();
	labelPlacer->SetInputConnection( pointSetToLabelHierarchy->GetOutputPort() );
	labelPlacer->SetIteratorType( vtkLabelHierarchy::QUEUE );
	labelPlacer->SetOutputTraversedBounds( false );
	labelPlacer->SetRenderer( m_renderer );
	labelPlacer->SetMaximumLabelFraction( 0.05 );
	//labelPlacer->UseDepthBufferOn();


	vtkLabeledDataMapper *ldm = vtkLabeledDataMapper::New();
	ldm->SetInputConnection(labelPlacer->GetOutputPort());
	ldm->SetLabelModeToLabelScalars();
	ldm->GetLabelTextProperty()->SetFontFamilyToArial();
	ldm->GetLabelTextProperty()->SetFontSize(10);
	ldm->GetLabelTextProperty()->SetColor(1,0,0);


	vtkActor2D *actor = vtkActor2D::New();
	actor->SetMapper(ldm);

	m_renderer->AddActor2D(actor);
	//addProper2D(actor);

	//display list labels;
}


void View2D::setDisplayMode(ViewMode mode)
{
	m_viewMode = mode;

	if ( m_viewMode == vmPickingSeed)
	{
		m_actorCrossLineV->GetProperty()->SetColor(128, 42.0, 42.0);
		m_actorCrossLineH->GetProperty()->SetColor(128.0, 42.0, 42.0);
		QTimer::singleShot(0, this, SLOT(slotPostSetMode()));
	}
	else if ( m_viewMode == vmNormal )
	{
		m_actorCrossLineV->GetProperty()->SetColor(65.0, 105.0, 225.0);
		m_actorCrossLineH->GetProperty()->SetColor(65.0, 105.0, 225.0);

		resetBackground();
	}
	else if ( m_viewMode == vmPixelGear)
	{
		m_actorCrossLineV->GetProperty()->SetColor(255.0/255.0, 128.0/255.0, 0/255.0);
		m_actorCrossLineH->GetProperty()->SetColor(255.0/255.0, 128.0/255.0, 0/255.0);

		m_renderer->SetBackground(82.0/255.0, 87.0/255.0, 110.0/255.0);

// 		vtkInteractorStyleRubberBand2D *testStyle = vtkInteractorStyleRubberBand2D::New();
// 		m_qvtkWidget->GetRenderWindow()->GetInteractor()->SetInteractorStyle(m_interactorStyle);
	}

	render();
}


void View2D::slotPostSetMode()
{
	for (int i = 0; i < 3; i++)
	{
		m_renderer->SetBackground(255, 255, 255);
		render();
		QTest::qSleep(50);
		m_renderer->SetBackground(0.1, 0.2, 0.4);
		QTest::qSleep(50);
		render();
		QTest::qSleep(50);
	}

	resetBackground();
}


void View2D::slotEnableTextInfo(bool toggled)
{
	if (toggled)
	{
		m_renderer->AddActor2D(m_textActorWindowLevel);
		m_renderer->AddActor2D(m_textActorIntensityValue);
	}
	else
	{
		m_renderer->RemoveActor2D(m_textActorWindowLevel);
		m_renderer->RemoveActor2D(m_textActorIntensityValue);
	}

	render();
}


void View2D::setCrossLineEnabled(bool flag)
{
	m_btnCrossLine->setChecked(flag);
}

bool View2D::isCrossLineEnabled()
{
	return m_btnCrossLine->isChecked();
}


void View2D::slotEnableCrossLine(bool toggled)
{
	if ( toggled)
	{
		m_renderer->AddActor(m_actorCrossLineV);
		m_renderer->AddActor(m_actorCrossLineH);
	}
	else
	{
		m_renderer->RemoveActor(m_actorCrossLineV);
		m_renderer->RemoveActor(m_actorCrossLineH);
	}

	render();
}


void View2D::showCrossLine(bool flag)
{
	if ( !isCrossLineEnabled())
		return;

	if (flag)
	{
		m_actorCrossLineH->SetVisibility(1);
		m_actorCrossLineV->SetVisibility(1);
	}
	else
	{
		m_actorCrossLineH->SetVisibility(0);
		m_actorCrossLineV->SetVisibility(0);
	}

	render();
}


void View2D::slotChangeSlice(vtkObject* object)
{
	static int ivalue = 0;
	ivalue = int(m_sliderRep->GetValue()+0.5);

	if ( m_sliderValue == ivalue)
		return;

	m_sliderValue = ivalue;
	changeSlice(m_sliderValue);
}

vtkImageData * View2D::baseImage()
{
	if ( m_imageList.size() > 0)
		return m_imageList.at(0);
	else
		return NULL;
}

void View2D::addBlendingImage( vtkImageData* image)
{
	int num = m_imageList.size();

	if ( num == 0)
	{
		qDebug() << "No base image";
		return;
	}

	if ( m_blendedImage)
	{
		QColor color = QColorDialog::getColor();

		vtkImageMapToColors *vtkcolor = vtkImageMapToColors::New();
		vtkcolor->SetInput(image);
		//m_blendingLookupTable->SetTableValue(1, 1, 0, 0);
		vtkLookupTable* lookuptalbe = vtkLookupTable::New();
		lookuptalbe->SetNumberOfColors(2);
		lookuptalbe->SetTableValue(0, 0, 0, 0, 0);
		lookuptalbe->SetTableValue(1, color.redF(), color.greenF(), color.blueF(), 0.3);

		vtkcolor->SetLookupTable(lookuptalbe);
		m_blendedImage->SetInput(num, vtkcolor->GetOutput());		
		m_blendedImage->Update();

		vtkcolor->Delete();
		lookuptalbe->Delete();

		m_imageList.push_back(image);

		render();
	}
}

void View2D::removeBlendedImage( vtkImageData* image)
{
	int num = m_imageList.size();

	if ( num == 0)
	{
		qDebug() << "No base image";
		return;
	}

	num = 0;
	QList<vtkImageData*>::iterator it = m_imageList.begin();
	for (; it != m_imageList.end(); it++, num++)
	{
		if ( *it == image)
		{
			if ( m_blendedImage)
			{
				m_blendedImage->SetInput(num, NULL);
				m_imageList.removeOne(image);
				render();
				return;
			}
		}
	}
}



QList<vtkImageData*>* View2D::imageList()
{
	return &m_imageList;
}

void View2D::pickSeed()
{
	setDisplayMode(vmPickingSeed);	
}

const QStringList& View2D::seedList()
{
	return m_seedList;
}

void View2D::removeSeed( QString str)
{
	m_seedList.removeOne(str);

	// and do others
  emit emitSeedPicked();
}

void View2D::seedSelected( QString str)
{
	qDebug() << "Seed: [" << str << "] selected";

	m_currSeed = str;
}

QString View2D::currentSeed()
{
	return m_currSeed;
}

void View2D::slotViewOrientationChanged( int index)
{
	switch(index)
	{
	case 0:
		m_viewOrientation = voAXIAL;
		break;
	case 1:
		m_viewOrientation = voCORONAL;
		break;
	case 2:
		m_viewOrientation = voSAGITTAL;
		break;
	default:
		break;
	}

	if (m_imageList.size() == 0)
		return;

	if ( m_viewOrientation == voAXIAL )
	{
		m_resliceAxes->DeepCopy(axialElements);
		m_resliceAxes->SetElement(0, 3, 0);
		m_resliceAxes->SetElement(1, 3, 0);
		m_resliceAxes->SetElement(2, 3, 0);
		m_sliderRep->SetMaximumValue(m_baseExtent[5]);
	}
	else if ( m_viewOrientation == voCORONAL)
	{
		m_resliceAxes->DeepCopy(coronalElements);
		m_resliceAxes->SetElement(0, 3, 0);
		m_resliceAxes->SetElement(1, 3, 0);
		m_resliceAxes->SetElement(2, 3, 0);
		m_sliderRep->SetMaximumValue(m_baseExtent[1]);
	}
	else if ( m_viewOrientation == voSAGITTAL)
	{
		m_resliceAxes->DeepCopy(sagittalElements);
		m_resliceAxes->SetElement(0, 3, 0);
		m_resliceAxes->SetElement(1, 3, 0);
		m_resliceAxes->SetElement(2, 3, 0);
		m_sliderRep->SetMaximumValue(m_baseExtent[3]);
	}

	m_sliderRep->SetValue(0);

	resetCamera();
	render();
}

ViewMode View2D::viewMode()
{

	return m_viewMode;
}